<?php

namespace Think;

/* 单个的Model */
class ModelSingle {

// 属性
// 当前数据库操作对象
protected $db               =   null;

// 主键名称
protected $pk               =   'id';
// 主键是否自动增长
protected $autoinc          =   false;    
// 字段信息
protected $fields           =   array();
// 模型名称
protected $name             =   '';
// 数据表前缀
protected $tablePrefix      =   null;
// 数据表名（不包含表前缀）
protected $tableName        =   '';
// 实际数据表名（包含表前缀）
protected $trueTableName    =   '';
// 数据库名称
protected $dbName           =   '';

// 是否自动检测数据表字段信息
protected $autoCheckFields  =   true;


/* __construct($name='',$tablePrefix='',$connection='') */
public function __construct($name,$tablePrefix,$dbName='',$db=null) {
	// 模型初始化
	$this->_initialize();				// 空

	// 获取模型名称
	if(!empty($name)) {
		$this->name = $name;
		$this->dbName = $dbName;
	}elseif(empty($this->name)){
		$this->name = $this->getModelName();
	}

	// 设置表前缀
	$this->tablePrefix = $tablePrefix;

	// 获取db连接
	$this->db = $db;

	// 字段检测	以前放置于 $this->db()中
	if(!empty($this->name) && $this->autoCheckFields){
		$this->_checkTableInfo();
	}
}
// _initialize() * 回调方法 初始化模型
protected function _initialize() {}
/* _checkTableInfo() * 自动检测数据表信息 */
protected function _checkTableInfo() {
	// 如果不是Model类 自动记录数据表信息
	// 只在第一次执行记录
	if(empty($this->fields)) {
		// 如果数据表字段没有定义则自动获取
		if(C('DB_FIELDS_CACHE')) {
			$db = $this->dbName?:C('DB_NAME');
			$fields = F('_fields/'.strtolower($db.'.'.$this->tablePrefix.$this->name));
			if($fields) {
				$this->fields = $fields;
				if(!empty($fields['_pk'])){
					$this->pk = $fields['_pk'];
				}
				return;
			}
		}

		// 如果不存在 重新获取
		$this->flush();
	}
}
/* flush() 获取字段信息并缓存
 * @access public
 * @return void
 */
public function flush() {
	// 缓存不存在则查询数据表信息
	$this->db->setModel($this->name);
	$fields = $this->db->getFields($this->getTableName());
	if(!$fields) { // 无法获取字段信息
		return false;
	}
	$this->fields = array_keys($fields);
	unset($this->fields['_pk']);
	foreach ($fields as $key=>$val){
		// 记录字段类型
		$type[$key] = $val['type'];
		if($val['primary']) {
			// 增加复合主键支持
			if (isset($this->fields['_pk']) && $this->fields['_pk'] != null) {
				if (is_string($this->fields['_pk'])) {
					$this->pk = array($this->fields['_pk']);
					$this->fields['_pk'] = $this->pk;
				}
				$this->pk[] = $key;
				$this->fields['_pk'][] = $key;
			} else {
				$this->pk = $key;
				$this->fields['_pk'] = $key;
			}
			if($val['autoinc']) $this->autoinc = true;
		}
	}
	// 记录字段类型信息
	$this->fields['_type'] =  $type;

	// 2008-3-7 增加缓存开关控制
	if(C('DB_FIELDS_CACHE')){
		// 永久缓存数据表信息
		$db = $this->dbName?:C('DB_NAME');
		F('_fields/'.strtolower($db.'.'.$this->tablePrefix.$this->name),$this->fields);
	}
}

// 数据表相关
/* getModelName() 得到当前的数据对象名称 $name
 * @access public
 * @return string
 */
public function getModelName() {
	if(empty($this->name)){
		$name = substr(get_class($this),0,-strlen(C('DEFAULT_M_LAYER')));
		if ( $pos = strrpos($name,'\\') ) {//有命名空间
			$this->name = substr($name,$pos+1);
		}else{
			$this->name = $name;
		}
	}
	return $this->name;
}
/* getTableName() 得到完整的数据表名
 * @access public
 * @return string
 */
public function getTableName() {
	if(empty($this->trueTableName)) {
		$tableName  = !empty($this->tablePrefix) ? $this->tablePrefix : '';
		if(!empty($this->tableName)) {
			$tableName .= $this->tableName;
		}else{
			$tableName .= parse_name($this->name);
		}
		$this->trueTableName = strtolower($tableName);
	}
	return (!empty($this->dbName)?$this->dbName.'.':'').$this->trueTableName;
}
/* getDbFields() 获取数据表字段信息 无_type van:去除->table()功能
 * @access public
 * @return array
 */
public function getDbFields(){
	if($this->fields) {
		$fields = $this->fields;
		unset($fields['_type'],$fields['_pk']);
		return $fields;
	}
	return false;
}

/* getFields() 获取数据表字段信息
 * @access public
 * @return array
 */
public function getFields(){
	return $this->fields;
}
/* getPk() 获取主键名称
 * @access public
 * @return string
 */
public function getPk() {
	return $this->pk;
}
/* getTablePrefix() 获取表前缀
 * @access public
 * @return array
 */
public function getTablePrefix() {
	return $this->tablePrefix;
}


}// class
